import { Node } from "../Node";
import { NodeStatus } from "../NodeStatus";
import { IControlNode } from "../interfaces/IControlNode";
import { INode } from "../interfaces/INode";



/**
 * 控制节点
 */
export abstract class ControlNode<T> extends Node<T> implements IControlNode<T> {

    protected $children: INode<T>[] = [];

    constructor(name: string,blackboard: T) {
        super(name,blackboard);
        this.$children = [];
    }

    AddChild(child: INode<T>) {
        if (this.$children.indexOf(child) > -1) {
            throw new Error("child already exists");
        }
        this.$children.push(child);
        child.parent = this;
    }

    GetChild(idx: number): INode<T> {
        if (idx < 0 || idx >= this.$children.length) {
            throw new Error("index out of range");
        }
        return this.$children[idx];
    }

    Halt(): void {
        this.HaltChildren();
        this.status = NodeStatus.IDLE;
    }

    HaltChild(idx: number): void {
        if (idx < 0 || idx >= this.$children.length) {
            throw new Error("index out of range");
        }
        const child = this.$children[idx];
        if (child.status === NodeStatus.RUNNING) {
            child.Halt();
        }
        this.status = NodeStatus.IDLE;
    }

    HaltChildren(start: number = 0): void {
        for (let i = start; i < this.$children.length; ++i) {
            this.HaltChild(i);
        }
    }

    Destroy(): void {
        this.HaltChildren();
        for (let i = 0; i < this.$children.length; ++i) {
            const child = this.$children[i];
            child.Destroy();
        }
        super.Destroy();
    }

    get numChildren(): number {
        return this.$children.length;
    }
}